<template>
  <div class="tinymce-box">
    <editor v-model="myValue" :init="init" :disabled="disabled" @onClick="onClick" :key="tinymceFlag">
    </editor>
  </div>
</template>

<script>
// 文档 http://tinymce.ax-z.cn/
// 引入组件
import "../../../public/tinymce"
import Editor from "@tinymce/tinymce-vue";

// 引入富文本编辑器主题的js和css
import "../../../public/tinymce/skins/content/default/content.css";
import "../../../public/tinymce/themes/silver/theme.js";
import "../../../public/tinymce/icons/default/icons.js"; // 解决了icons.js 报错Unexpected token '<'
import '../../../public/tinymce/skins/ui/oxide/skin.css'
import "tinymce-plugin";

// 编辑器插件plugins
// 更多插件参考：https://www.tiny.cloud/docs/plugins/

import "@wiris/mathtype-tinymce5/plugin.min.js";
import tinymce from '../../../public/tinymce';
import tinymcePlugin from 'tinymce-plugin';
import { getToken } from "@/utils/auth";
import { v4 as uuidv4 } from 'uuid';
import { highlightInit,observer,closeControls,closeHighlightActive } from './plugins/highlight.js'
import { subfieldinit,clear as subfieldClear } from './plugins/subfield.js'
import { groupInit,closeStyleHandle } from './plugins/styleGroup.js'
import { TimeSelect } from 'element-ui';
export default {
  components: {
    Editor,
  },
  name: "Tinymce",
  props: {
    // 默认的富文本内容
    value: {
      type: String,
      default: "",
    },
    // 基本路径，默认为空根目录，如果你的项目发布后的地址为目录形式，
    // 即abc.com/tinymce，baseUrl需要配置成tinymce，不然发布后资源会找不到
    baseUrl: {
      type: String,
      default: window.location.origin ? window.location.origin : "",
    },
    // 禁用
    disabled: {
      type: Boolean,
      default: false,
    },
    // 是否开启高亮块插件
    highlight: {
      typeof: Boolean,
      default: false,
    },
    plugins: {
      type: [String, Array],
      default:
        "lineheight paste pastewordimage formatpainter print preview searchreplace autolink directionality visualblocks visualchars image link media template \
        code codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists wordcount textpattern autosave mathjax indent2em",
    },
    toolbar: {
      type: [String, Array],
      default: "undo redo removeformat formatpainter  fontselect  fontsizeselect formatselect  bold italic underline forecolor indent2em superscript subscript | alignment \
      lineheight numlist bullist  table tiny_mce_wiris_formulaEditor tiny_mce_wiris_formulaEditorChemistry mathjax"
      // default:
      //  "undo redo removeformat formatpainter fontselect fontsizeselect styleselect tiny_mce_wiris_formulaEditor tiny_mce_wiris_formulaEditorChemistry | cut copy paste pastetext | forecolor backcolor bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify outdent indent |  formatselect  | bullist numlist | blockquote subscript superscript | table image media charmap hr pagebreak insertdatetime print preview | code selectall searchreplace visualblocks | indent2em lineheight axupimgs",
    },
    height: {
      type: String,
      default: "100vh"
    },
    statusbar: {
      type: Boolean,
      default: true,
    },
    fromBase: {
      type: Boolean,
      default: false,
    },
    placeholder: {
      type: String,
      default: "",
    },
    editorSetup: {
      type: Function,
      default: function () { }
    },
  },
  data() {
    return {
      isPasteOperation: false,
      isWaiting: false,
      timer: null,
      prevPosition: {},
      tinymceFlag: 1,
      init: {
        placeholder: this.placeholder,
        language_url: '/tinymce/langs/zh_CN.js',  // 引入语言包文件
        fontsize_formats: '12px 14px 16px 18px 20px 24px 30px 36px 42px',
        language: 'zh_CN',
        font_formats: '微软雅黑=Microsoft YaHei;宋体=simsun;新宋体=NSimSun;仿宋=FangSong;楷体=KaiTi;黑体=SimHei;Arial=arial;AndaleMono=andale mono;Arial Black=arial black;Comic Sans MS=comic sans ms;Impact=Impact;Times New Roman=Times New Roman;Symbol=symbol;',
        selector: 'vue-tinymce-' + +new Date(),
        height: this.height,
        min_height: 100,
        skeletonScreen: true,
        toolbar_sticky: false,
        elementpath: false, // 元素路径是否显示
        statusbar: this.statusbar,
        paste_auto_cleanup_on_paste: true,
        paste_remove_styles: true,
        paste_remove_styles_if_webkit: true,
        paste_strip_class_attributes: true,
        paste_as_text: this.fromBase,
        custom_undo_redo_levels: 30, //撤销次数
        toolbar_groups: {
          alignment: {
            icon: 'align-left',
            tooltip: 'alignment',
            items: 'alignleft aligncenter alignright alignjustify',
          }
        },
        //table_toolbar: "tablealignleft tablealigncenter tablealignright tableprops",
        table_toolbar: "tableprops tabledelete | tableinsertrowbefore tableinsertrowafter tabledeleterow | tableinsertcolbefore tableinsertcolafter tabledeletecol | tablealignleft tablealigncenter tablealignright | threeline",
        quickbars_insert_toolbar: false,
        lineheight_formats: "1 1.15 1.5 1.75 2 2.5 3",  // 行高配置，也可配置成"12px 14px 16px 20px"这种形式
        body_class: 'panel-body ',
        branding: false, // 商标消息” Powered by TinyMCE”的显示与隐藏
        resize: false,
        media_live_embeds: true, // 启用此选项后，用户将看到可编辑区域内嵌入视频内容的实时预览，而不是占位符图像
        object_resizing: true, // 此选项允许您打开/关闭图像、表格或媒体对象的大小调整手柄。默认情况下，此选项处于启用状态，允许您调整表和图像的大小。您还可以指定要启用大小调整的 CSS3 选择器。
        menubar: false, // 菜单栏
        toolbar: this.toolbar,
        plugins: this.plugins,
        end_container_on_empty_block: true,
        powerpaste_word_import: 'clean',
        code_dialog_height: 450,
        code_dialog_width: 1000,
        convert_urls: false,//取消将图片绝对路径改成相对路径
        relative_urls: false,
        remove_script_host: false,
        default_link_target: '_blank',
        link_title: false, // 对话框中“标题”的显示开关
        file_picker_types: "media",
        images_file_types: 'jpg,jpeg,png,gif,svg',
        verify_html: false,
        powerpaste_word_import: 'merge',// 参数可以是propmt, merge, clear，效果自行切换对比
        powerpaste_html_import: 'merge',// propmt, merge, clear
        powerpaste_allow_local_images: true,
        forced_root_block: 'div', // 强制根块元素div
        //toolbar_mode: "wrap",
        // toolbar_drawer: 'wrap', // 工具栏模式
        content_css: this.fromBase ? '' : ('/tinymce/mycontent.css?' + new Date().getTime()),
        codesample_languages: [
          { text: 'HTML/XML', value: 'markup' },
          { text: 'JavaScript', value: 'javascript' },
          { text: 'CSS', value: 'css' },
          { text: 'PHP', value: 'php' },
          { text: 'Ruby', value: 'ruby' },
          { text: 'Python', value: 'python' },
          { text: 'Java', value: 'java' },
          { text: 'C', value: 'c' },
          { text: 'C#', value: 'csharp' },
          { text: 'C++', value: 'cpp' }
        ],
        init_instance_callback: editor => {
          //修改数学公式和化学公式的icon 需要改一下 多个编辑器组件被引用时只有倒数二三图标会更换 而且对应内容也有问题
          if(document.querySelector('[title="插入数学公式 - MathType"]')) {
            document.querySelector('[title="插入数学公式 - MathType"]').innerHTML = '<span class="tox-icon tox-tbtn__icon-wrap"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M4.78598 11.9933C5.03552 11.875 5.33368 11.9814 5.45194 12.231L7.66632 16.9032L10.5834 5.87225C10.6414 5.65288 10.8399 5.50008 11.0668 5.50008L19.0001 5.50007C19.2763 5.50007 19.5001 5.72393 19.5001 6.00007C19.5001 6.27622 19.2763 6.50007 19.0001 6.50007L11.4517 6.50008L8.2835 18.4808C8.22983 18.6838 8.0551 18.8316 7.84607 18.8509C7.63703 18.8702 7.4382 18.7569 7.34829 18.5672L4.54829 12.6592C4.43003 12.4097 4.53644 12.1115 4.78598 11.9933Z" fill="#3E4D71"/></svg></span>'
          }
          if(document.querySelector('[title="插入化学分子式 - ChemType"]')) {
            document.querySelector('[title="插入化学分子式 - ChemType"]').innerHTML = '<span class="tox-icon tox-tbtn__icon-wrap"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M11.5 4.42407L18.2481 8.28011C18.4878 8.41712 18.5711 8.72254 18.4341 8.9623C18.2971 9.20206 17.9917 9.28536 17.7519 9.14835L11.5 5.57582L5.5 9.00439V15.8526L11.5 19.2812L17.7519 15.7087C17.9917 15.5717 18.2971 15.655 18.4341 15.8947C18.5711 16.1345 18.4878 16.4399 18.2481 16.5769L11.5 20.433L4.5 16.433V8.42407L11.5 4.42407Z" fill="#3E4D71"/></svg></span>'
          }
          if (this.html) {
            editor.setContent(this.html)
          }
          this.hasInit = true
          editor.on('NodeChange Change KeyUp SetContent', () => {
            console.log('--------')
            this.hasChange = true
            this.$emit('input', editor.getContent())
            this.editorContent = editor.getContent()
          })
          editor.on('input', (e) => {
            console.log('--------1')
            console.log(e.target,8888)
            // 兼容搜狗placeholder
            if (e.currentTarget) {
              if (!e.currentTarget.innerText || e.currentTarget.innerText === '\n') {
                e.currentTarget.setAttribute(
                  'data-mce-placeholder',
                  this.placeholder
                );
              } else {
                e.currentTarget.removeAttribute('data-mce-placeholder');
              }
            }
          });
          // editor.on('ScrollContent', (e) => {
          //   console.log(e)
          // });

          editor.on('ExecCommand', (e) => {
            // 插入内容事件
            // if (e.command === 'mceInsertContent') {//放开是为了解决切换目录后双击事件消失，没办法了
            editor.dom.select('.can-edit').forEach(item => {
              editor.dom.unbind(item, 'click')
              editor.dom.bind(item, 'click', this.handleClick(editor))
            })
            // }
            // 自定义卡片移出隐藏操作区
            editor.dom.select('.card-autonomy-editor').forEach(item => {
              const cardBtn = item.querySelector('.card-autonomy-editor-btn')
              const isUnfold = item.querySelector('.card-autonomy-editor-menu-active')
              editor.dom.unbind(item, 'mouseout')
              editor.dom.bind(item, 'mouseout', ()=>{
                if(!isUnfold){
                  cardBtn.style.visibility = 'hidden'
                }
              })
            })

          });
          editor.dom.select('.can-edit').forEach(item => {
            editor.dom.bind(item, 'click', this.handleClick(editor))
          })
          if(!this.fromBase) {
            // 高亮块引入
            if(this.highlight)highlightInit(editor)
            // 分栏
            subfieldinit(editor)
            // 样式组
            groupInit(editor)
            // 编辑区外点击关闭高亮样式库功能
            this.initEditExcludeClick()
          }

        },
        paste_preprocess: function (plugin, args) {
          this.isPasteOperation = true; // 设置标志变量为 true，表示当前是粘贴操作
          console.log('粘贴', args)
        },
        setup: editor => {

          editor.on('FullscreenStateChanged', e => {
            this.fullscreen = e.state
          })

          editor.on('scroll', (e) => {
            console.log('--------scroll')
          });

          // 监听NodeChange事件以检查新元素
          editor.on('NodeChange', function (e) {
            const node = editor.selection.getNode(); // 获取当前选中的节点
            const nodeUuid = tinymce.DOM.getAttrib(node,'data-uuid')
            const previousUuid = tinymce.DOM.getAttrib(node.previousElementSibling,'data-uuid')
            if (node && ['P', 'TABLE', 'DIV','TD','H1','H2','H3','H4','H5','H6','H7'].includes(node.nodeName) && (!node.getAttribute('data-uuid') || this.isPasteOperation || nodeUuid === previousUuid)) {
              this.isPasteOperation = false;
              const uuid = uuidv4().substring(0 ,24);
              if(['TD'].includes(node.nodeName)) {
                tinymce.DOM.setAttrib(node.closest('table'), 'data-uuid', uuid);
              } else {
                tinymce.DOM.setAttrib(node, 'data-uuid', uuid);
              }
            }
            observer(editor)
          });
          this.editorSetup(editor)
        },
        images_upload_handler: (blobInfo, succFun, failFun) => {//上传图片
          var xhr, formData;
          var file = blobInfo.blob();//转化为易于理解的file对象
          if (file.size > 1024 * 1024 * 20) {
            failFun('上传图片大小不能超过20MB!');
            return
          }
          let isImg = false;
          let fileType = ['jpg','jpeg','png','gif','svg'];
          if (fileType.length) {
            let fileExtension = "";
            if (file.name.lastIndexOf(".") > -1) {
              fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
            }
            isImg = fileType.some(type => {
              if (file.type.indexOf(type) > -1) return true;
              if (fileExtension && fileExtension.indexOf(type) > -1) return true;
              return false;
            });
          }
          if(!isImg) {
            failFun(`文件格式不正确, 请上传${fileType.join("/")}图片格式文件!`);
            return
          }
          console.log(file)
          xhr = new XMLHttpRequest();
          xhr.withCredentials = false;
          xhr.open('POST', process.env.VUE_APP_BASE_API + "/resource/upload");
          xhr.setRequestHeader('Header-Token', getToken());
          xhr.onload = function () {
            var json;
            if (xhr.status != 200) {
              failFun('HTTP Error: ' + xhr.status);
              return;
            }
            json = xhr.responseText;
            if (!json) {
              failFun('Invalid JSON: ' + xhr.responseText);
              return;
            }
            succFun(json);
          };
          formData = new FormData();
          formData.append('file', file, file.name);
          xhr.send(formData);
        },
        file_picker_callback: function (callback, value, meta) {//上传视频音频
          //文件分类
          var filetype = '.mp3, .mp4, .mov';
          //后端接收上传文件的地址
          var upurl = process.env.VUE_APP_BASE_API + "/resource/upload";

          //模拟出一个input用于添加本地文件
          var input = document.createElement('input');
          input.setAttribute('type', 'file');
          input.setAttribute('accept', filetype);
          input.click();
          input.onchange = function () {
            var file = this.files[0];
            var xhr, formData;
            console.log(file.name);
            xhr = new XMLHttpRequest();
            xhr.withCredentials = false;
            xhr.open('POST', upurl);
            xhr.setRequestHeader('Header-Token', getToken());
            xhr.onload = function () {
              var json;
              if (xhr.status != 200) {
                this.$message.error('HTTP Error: ' + xhr.status);
                return;
              }
              json = xhr.responseText;
              if (!json) {
                this.$message.error('HTTP Error: ' + xhr.responseText);
                return;
              }
              callback(json);
            };
            formData = new FormData();
            formData.append('file', file, file.name);
            xhr.send(formData);
          };
        },
        external_plugins: {
          tiny_mce_wiris: this.fromBase? '':`node_modules/@wiris/mathtype-tinymce5/plugin.min.js`,
          'powerpaste': '/tinymce/plugins/powerpaste/plugin.min.js'
        },
        mathjax: {
          lib: 'tinymce/plugins/mathjax/tex-svg.js',
        }
      },
      myValue: this.value,
      cropOff:false
    };
  },
  mounted() {
    tinymce.init({});
  },
  activated() {
    this.tinymceFlag++
  },
  methods: {
    // 添加相关的事件，可用的事件参照文档=> https://github.com/tinymce/tinymce-vue => All available events
    // 需要什么事件可以自己增加

    // 回退关闭所有样式插件
    backCloseAll(e) {
      console.log('popstate',e,window.location.href)
      closeStyleHandle()
      closeControls()
      subfieldClear()
    },

    // 初始化编辑区域外点击事件
    initEditExcludeClick(){
      this.$nextTick(()=>{
      const container = document.querySelector('.tox-editor-container')
        if(container){
          container.addEventListener('click',e=>{
            // e.stopPropagation()
            // e.preventDefault()
            if(e.target.classList.contains('tox-editor-container')){
              console.log(e,'触发关闭事件')
              closeStyleHandle()
              closeControls()
              subfieldClear()
              closeHighlightActive()
            }
          })
        }
      })
    },
    onClick(e) {
      this.$emit("onClick", e, tinymce);
    },
    // 可以添加一些自己的自定义事件，如清空内容
    clear() {
      this.myValue = "";
    },
    CompareHeight(){
      let templateV1Height = this.$refs.templateV1.offsetHeight
      let bgImgHeight = this.$refs.bgImg.offsetHeight
      if(bgImgHeight<=150 && templateV1Height <= 150){
        console.log('布局一，图片高度小于等于文本高度')
        this.bgImgStyle = {
          height:`150px`
        }
        this.initialHeight = 150
      }else{
        if(templateV1Height > bgImgHeight){
          this.cropOff = true
          this.bgImgStyle = {
            height:`${templateV1Height}px`
          }
        }else{
          console.log(templateV1Height,bgImgHeight)
          if(this.cropOff){
            if(templateV1Height<this.initialHeight){
              templateV1Height = this.initialHeight
            }
            this.bgImgStyle = {
              height:`${templateV1Height}px`
            }
          }
        }
      }
    },
    getDoc(){
      const doc = tinymce.activeEditor.contentDocument
      return doc
    },
    getScrollTop(){
      return tinymce.activeEditor.dom.getViewPort(tinymce.activeEditor.getWin()).y
    },
    getContent() {
      return tinymce.activeEditor.getContent();
    },
    insertHtml(html) {
      console.log(html);
      //html = " <b>bolded text</b> "
      tinymce.activeEditor.insertContent(html)
      //tinymce.activeEditor.execCommand('mceInsertContent', false, html);
      //tinymce.activeEditor.execCommand('mceInsertContent', false, "<span>&nbsp;</span>");//为了去除插入后带来的样式
    },
    getHtml(selector = 'h1,h2,h3,h4,h5,h6') {
      const _doc = tinymce.activeEditor.dom?tinymce.activeEditor.dom.doc:''
      const content =_doc? _doc.querySelectorAll(selector):''
      return content
    },
    insertCss(html) {//样式库插入
      let editor = tinymce.activeEditor
      let nHtml = editor.selection.getContent() || '读书不是为了雄辩和驳斥，也不是为了轻信和盲从，而是为了思考和权衡。'
      console.log(editor.selection.getContent())
      editor.selection.setContent(html.replace(/iamzkcmkjzyfont/g, nHtml));
    },
    switchDirectory() {//切换目录的时候需要清空撤销事件
      //tinymce.activeEditor.execCommand('SearchReplace'); ScrollWindow
      //tinymce.activeEditor.undoManager.clear()
      console.log(tinymce.activeEditor)
    },
    tiggerTinymceBar(type) {//主动触发编辑器的toolbar/SearchReplace
      //tinymce.activeEditor.execCommand('mceTableToggleClass', false, 'myclass');
      tinymce.activeEditor.execCommand(type);
    },
    getText() {
      if(tinymce.activeEditor.selection) {
        return tinymce.activeEditor.selection.getContent({format: 'text'})
      } else {
        return "";
      }
    },
    // 处理编辑器内部指定元素的点击事件
    handleClick(editor) {
      const that = this
      return function (e) {
        that.$emit('oneClick', e, editor)
        if (this.timer) {
          clearTimeout(this.timer)
          this.timer = null
        }
        const { pageX, pageY } = e
        if (this.isWaiting) {
          // clearTimeout(this.timer)
          // this.timer = null
          this.isWaiting = false
          const diffX = Math.abs(pageX - this.prevPosition.pageX)
          const diffY = Math.abs(pageY - this.prevPosition.pageY)
          // 如果满足位移小于10，则是双击
          console.log(diffX)
          if (diffX <= 10 && diffY <= 10) {
            // 取消当前事件传递
            e.stopPropagation()
            console.log('---doubleClick')
            that.$emit('doubleClick', e, editor)
          }
          clearTimeout(this.timer)
          this.timer = null
          this.prevPosition = {}
        } else {
          this.prevPosition = { pageX, pageY }
          // 阻止冒泡，不让事件继续传播
          //e.stopPropagation()
          // 开始等待第2次点击
          this.isWaiting = true
          this.timer = setTimeout(() => {
            this.isWaiting = false
          }, 350)
        }
      }
    }
  },
  beforeDestroy() {
    clearTimeout(this.timer)
    this.timer = null
    this.backCloseAll()
  },
  watch: {
    value(newValue) {
      this.myValue = newValue;
    },
    myValue(newValue) {
      this.$emit("input", newValue);
    },
  },
};
</script>

<style lang='scss' scoped>
.tinymce-box{
  background: #ebeff6;
}
.tox .tox-sidebar-wrap {
  width: 800px;
  margin: 0 auto;
}
  #tinymce p {margin: 0;}
  .tinymce{padding:20px;border-radius:10px;background:#fff;width:100%;}
  .tinymce-container{position: relative;width:100%;}
  .tinymce-container >>> .mce-fullscreen {
    z-index: 10000;
  }
  .tinymce-textarea {
    visibility: hidden;
    z-index: -1;
  }
  .editor-custom-btn-container {
    position: absolute;
    right: 4px;
    top: 4px;
  }
  .fullscreen .editor-custom-btn-container {
    z-index: 10000;
    position: fixed;
  }
  .editor-upload-btn {
    display: inline-block;
  }
  // 隐藏底部logo栏
  .mce-edit-area + .mce-statusbar {
    opacity: 0;
    height: 0;
  }
  </style>
